import ctypes
import os
import sys
import subprocess

def _init_macos_gui_subsystem():
    """
    Initialize macOS GUI subsystem to prevent hanging when loading GUI libraries
    This must be called before loading libraries that depend on Cocoa/AppKit
    """
    try:
        import threading
        # Check if we're on the main thread
        if threading.current_thread() is threading.main_thread():
            print("Initializing macOS GUI subsystem...")
            
            # Try to initialize the application event loop
            # This prevents hanging when GUI frameworks are loaded
            from ctypes import cdll, c_void_p, c_bool
            from ctypes.util import find_library
            
            # Load Foundation framework
            foundation = cdll.LoadLibrary('/System/Library/Frameworks/Foundation.framework/Foundation')
            
            # Load AppKit framework 
            appkit = cdll.LoadLibrary('/System/Library/Frameworks/AppKit.framework/AppKit')
            
            # Get NSApplication class
            foundation.objc_getClass.restype = c_void_p
            foundation.objc_getClass.argtypes = [ctypes.c_char_p]
            
            # Get selector for sharedApplication
            foundation.sel_registerName.restype = c_void_p
            foundation.sel_registerName.argtypes = [ctypes.c_char_p]
            
            # Get NSApp shared instance
            NSApplication = foundation.objc_getClass(b'NSApplication')
            sharedApplication = foundation.sel_registerName(b'sharedApplication')
            
            # Call [NSApplication sharedApplication] to ensure app is initialized
            foundation.objc_msgSend.restype = c_void_p
            foundation.objc_msgSend.argtypes = [c_void_p, c_void_p]
            
            nsapp = foundation.objc_msgSend(NSApplication, sharedApplication)
            
            if nsapp:
                print("NSApplication initialized successfully")
                return True
            else:
                print("Warning: Failed to initialize NSApplication")
                return False
        else:
            print("Warning: Not on main thread, skipping GUI initialization")
            return True
            
    except Exception as e:
        print(f"Warning: Failed to initialize macOS GUI subsystem: {e}")
        print("Continuing anyway...")
        return False

def setup_soui_dll_path(rootDir, bAbsPath=False):
    """设置SOUI DLL搜索路径"""
    # 检测系统架构：64位系统上指针大小为8字节
    import platform
    x64 = (platform.machine().endswith('64') or sys.maxsize > 2**32)
    
    if sys.platform.startswith('win'):
        soui_dll_path = os.path.join(rootDir, "soui5/windows", ('x64' if x64 else 'x86'), "bin", "Release")
        if(bAbsPath):
            soui_dll_path = rootDir
        # 确保路径存在
        if os.path.exists(soui_dll_path):
            print(f"Setting DLL directory to: {soui_dll_path}")
            # 使用SetDllDirectory设置DLL搜索路径
            try:
                result = ctypes.windll.kernel32.SetDllDirectoryW(soui_dll_path)
                if result:
                    return True
                else:
                    error_code = ctypes.windll.kernel32.GetLastError()
                    print(f"Failed to set DLL directory, error code: {error_code}")
            except Exception as e:
                print(f"Exception while setting DLL directory: {e}")
    elif sys.platform.startswith('darwin'):  # macOS
        soui_dll_path = os.path.join(rootDir, "soui5/macos", "x64", "lib", "Release")
        if(bAbsPath):
            soui_dll_path = rootDir
        # 确保路径存在
        if os.path.exists(soui_dll_path):
            print(f"Setting library directory to: {soui_dll_path}")
            # 在macOS上使用DYLD_LIBRARY_PATH作为备选方案
            try:
                # 设置DYLD_LIBRARY_PATH环境变量
                current_path = os.environ.get('DYLD_LIBRARY_PATH', '')
                if current_path:
                    new_path = f"{soui_dll_path}:{current_path}"
                else:
                    new_path = soui_dll_path
                os.environ['DYLD_LIBRARY_PATH'] = new_path
                print(f"DYLD_LIBRARY_PATH set to: {new_path}")
                
                # macOS特殊处理：初始化GUI子系统
                _init_macos_gui_subsystem()
                return True
            except Exception as e:
                print(f"Exception while setting library path: {e}")
                return False
    elif sys.platform.startswith('linux'):  # Linux
        soui_dll_path = os.path.join(rootDir, "soui5/linux", "x64", "lib", "Release")
        if(bAbsPath):
            soui_dll_path = rootDir
        # 确保路径存在
        if os.path.exists(soui_dll_path):
            print(f"Setting library directory to: {soui_dll_path}")
            # 在Linux上设置动态库搜索路径
            try:
                # 方法1: 设置LD_LIBRARY_PATH环境变量
                current_path = os.environ.get('LD_LIBRARY_PATH', '')
                if current_path:
                    new_path = f"{soui_dll_path}:{current_path}"
                else:
                    new_path = soui_dll_path
                os.environ['LD_LIBRARY_PATH'] = new_path
                print(f"LD_LIBRARY_PATH set to: {new_path}")

                # 方法2: 使用ctypes预加载关键的共享库
                # 这确保在导入soui4py之前，依赖的库已经被加载
                critical_libs = [
                    'libsoui4.so',
                    'libswinx.so',
                    'libutilities4.so',
                    'liblog4z.so',
                    'libimgdecoder-stb.so',
                    'librender-gdi.so',
                    'librender-skia.so',
                    'libresprovider-zip.so',
                    'libresprovider-7zip.so',
                    'libtranslator.so',
                    'libtaskloop.so',
                    'libscriptmodule-lua.so',
                    'libmsftedit.so',
                    'libsipcobject.so'
                ]

                loaded_libs = []
                for lib_name in critical_libs:
                    lib_path = os.path.join(soui_dll_path, lib_name)
                    if os.path.exists(lib_path):
                        try:
                            # 使用RTLD_GLOBAL标志确保符号全局可见
                            lib_handle = ctypes.CDLL(lib_path, mode=ctypes.RTLD_GLOBAL)
                            loaded_libs.append(lib_name)
                            print(f"Successfully preloaded: {lib_name}")
                        except Exception as lib_e:
                            print(f"Warning: Failed to preload {lib_name}: {lib_e}")
                    else:
                        print(f"Warning: Library not found: {lib_path}")

                if loaded_libs:
                    print(f"Preloaded {len(loaded_libs)} critical libraries")
                    return True
                else:
                    print("Warning: No critical libraries were preloaded")
                    return True  # 仍然返回True，因为LD_LIBRARY_PATH已设置

            except Exception as e:
                print(f"Exception while setting library path: {e}")
                return False
    return False
